package com.blog.service.content.impl;

import com.blog.constant.ErrorConstant;
import com.blog.constant.Types;
import com.blog.dto.cond.ContentCondition;
import com.blog.exception.BusinessException;
import com.blog.mapper.CommentMapper;
import com.blog.mapper.ContentMapper;
import com.blog.mapper.RelationshipMapper;
import com.blog.model.Comment;
import com.blog.model.Content;
import com.blog.model.Relationship;
import com.blog.service.content.ContentService;
import com.blog.service.meta.MetaService;
import com.blog.utils.MethodUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 文章服务层的业务层接口实现类
 *
 * @author wmb
 *
 * @date 2020-2-8
 */
@Service("contentService")
@Transactional
public class ContentServiceImpl implements ContentService {

    @Autowired
    @Qualifier("contentMapper")
    private ContentMapper contentMapper;

    @Autowired
    @Qualifier("metaService")
    private MetaService metaService;

    @Autowired
    @Qualifier("relationshipMapper")
    private RelationshipMapper relationshipMapper;

    @Autowired
    @Qualifier("commentMapper")
    private CommentMapper commentMapper;

    /**
     * 根据条件获取文章列表
     *
     * @param contentCondition
     * @param pageNum
     * @param pageSize
     *
     * @return
     */
    @Override
    @Cacheable(value = "articleCaches", key = "'articlesByCond_' + #p1 + 'type_' + #p0.type")
    public PageInfo<Content> getArticlesByCond(ContentCondition contentCondition, Integer pageNum, Integer pageSize) {
        if (contentCondition == null) {
            throw new BusinessException(ErrorConstant.PARAM_IS_NULL, MethodUtil.getLineInfo());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Content> contentList = contentMapper.getArticlesByCondition(contentCondition);
        return new PageInfo<>(contentList);
    }

    /**
     * 添加文章
     *
     * @param content
     *
     * @return
     */
    @Override
    @CacheEvict(value={"articleCache", "articleCaches"}, allEntries=true, beforeInvocation=true)
    public void addArticle(Content content) {
        if (content == null) {
            throw new BusinessException(ErrorConstant.PARAM_IS_NULL, MethodUtil.getLineInfo());
        }

        contentMapper.saveArticle(content);

        // 保存文章标签和分类
        saveMeta(content);
    }


    /**
     * 更新文章
     *
     * @param content
     *
     * @return
     */
    @Override
    @CacheEvict(value={"articleCache", "articleCaches"}, allEntries=true, beforeInvocation=true)
    public void updateArticleById(Content content) {
        contentMapper.updateArticleById(content);

        relationshipMapper.deleteRelationshipByCid(content.getId());

        // 保存文章标签和分类
        saveMeta(content);
    }

    /**
     * 根据编号获取文章
     *
     * @param cid
     *
     * @return
     */
    @Override
    @Cacheable(value = "articleCache", key = "'atricleById_' + #p0")
    public Content getArticleById(Integer cid) {
        return contentMapper.getArticleById(cid);
    }

    /**
     * 根据编号删除文章
     *
     * @param cid
     *
     * @return
     */
    @Override
    @CacheEvict(value={"articleCaches", "articleCache"}, allEntries=true, beforeInvocation=true)
    public void deleteArticleById(Integer cid) {
        contentMapper.deleteArticleById(cid);

        // 删除该文章下的所有评论
        List<Comment> commentList = commentMapper.getCommentsByCid(cid);
        if (CollectionUtils.isNotEmpty(commentList)) {
            commentList.forEach(comment -> {
                commentMapper.deleteCommentById(comment.getId());
            });
        }

        // 删除标签和分类关联
        List<Relationship> relationshipList = relationshipMapper.getRelationshipByCid(cid);
        if (CollectionUtils.isNotEmpty(relationshipList)) {
            relationshipList.forEach(relationship -> {
                relationshipMapper.deleteRelationshipByCid(cid);
            });
        }
    }

    /**
     * 添加文章点击量
     *
     * @param content
     */
    @Override
    @CacheEvict(value={"articleCaches", "articleCache"}, allEntries=true, beforeInvocation=true)
    public void updateArticleByCid(Content content) {
        if (content != null && content.getId() != null) {
            contentMapper.updateArticleById(content);
        }
    }

    /**
     * 更新分类
     *
     * @param ordinal
     * @param newCategory
     */
    @Override
    @CacheEvict(value={"articleCaches", "articleCache"}, allEntries=true, beforeInvocation=true)
    public void updateCategory(String ordinal, String newCategory) {
        ContentCondition contentCondition = new ContentCondition();
        contentCondition.setCategory(ordinal);
        List<Content> contentList = contentMapper.getArticlesByCondition(contentCondition);
        contentList.forEach(content -> {
            content.setCategories(content.getCategories().replace(ordinal, newCategory));
            contentMapper.updateArticleById(content);
        });
    }

    /**
     * 保存文章标签和分类
     *
     * @param content
     */
    private void saveMeta(Content content) {
        // 文章标签和分类
        String tags = content.getTags();
        String categories = content.getCategories();

        Integer cid = content.getId();
        metaService.saveMetas(cid, tags, Types.TAG.getType());
        metaService.saveMetas(cid, categories, Types.CATEGORY.getType());
    }
}
